/*
 * Map.java
 *
 * Created on August 6, 2004, 10:42 PM
 */

/**
 *
 * @author  pablo
 */

package edu.umd.essic.maskbuilder;

import java.net.URL;
import java.net.MalformedURLException;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.image.renderable.*;
import java.awt.geom.*;
import com.sun.image.codec.jpeg.*;
import java.nio.*;
import java.nio.channels.*;
import java.awt.Color.*;
import javax.swing.JOptionPane;
import java.awt.geom.*;

public class Map {
   private int width, height;
   private BufferedImage image;
   private BufferedImage  zoomedimage;
   private Rectangle rect;
   private boolean rect_selected = false;
   private double upper_y, left_x;
   private float Upper_y, Left_x, scale_factor;
   private int threshold, DataType, Precision, Nbytes, Length;
   private float nlon, nlat; // size in degrees
   private int[][] data;
   private float[][] itopo;
   private int Nlon, Nlat, Nlon_pr, Nlat_pr, MINval,MAXval,DeltaLon, DeltaLat, size_x, size_y;
   public Color[] land_col, ocean_col;
   public static int land_ncol  = 512;
   public static int ocean_ncol = 512;
   private boolean FileNotFound = false;
   private boolean itopo_exist  = false;
   private int Nlon1, Nlon2;
       
    /** Creates a new instance of Map */
    public Map(File f, MapFileDlg mfd, boolean NoDialog) {
        LoadFileHeader(f,mfd, NoDialog);
    }
    
    public int GetWidth(){
        return width;
    }
    
    public int GetHeight(){
        return height;
    }
    
    public void ResetThreshold(int value){
        threshold = value; 
    }
    
    public int GetThreshold(){
        return threshold;
    }
    
    public float[][] GetTopoIndices(){
        return itopo;
    }
    
    public void LoadFileHeader(File f, MapFileDlg mfd, boolean NoDialog){
        ReadFileHeader(f);
        if (!FileNotFound){ 
            threshold = 0;
            nlon = getNLON();
            nlat = getNLAT();
            float Right_x = Left_x+nlon;
            if (Right_x > 180) Right_x = -360+Right_x;
            float Lower_y = Upper_y-nlat;
            mfd.DataType = DataType;
            mfd.CellSize = DeltaLat;
            mfd.LeftX_init   = Left_x;
            mfd.UpperY_init  = Upper_y;
            mfd.RightX_init  = Right_x;
            mfd.LowerY_init  = Lower_y;
            mfd.MINval       = MINval;
            mfd.MAXval       = MAXval;
            mfd.Nlon_init    = Nlon;
            mfd.Nlat_init    = Nlat;
            mfd.Precision    = Precision; 
            mfd.Nbytes       = Nbytes; 
            if (NoDialog) {
                mfd.OnShown();
                mfd.OnOK = true;
            } else mfd.show();
        }        
    }   
    
    public void LoadFileData(File f, MapFileDlg mfd){
        long nbytetoskip = 0;            
        threshold = (int)mfd.Threshold;
        Nlon_pr = Nlon;
        Nlat_pr = Nlat;
        Nlon = mfd.Nlon;
        Nlat = mfd.Nlat;
        nbytetoskip = Length+(int)(Nbytes*Nlon_pr*(int)(Upper_y-mfd.Upper_y)*3600/DeltaLat);
        float x = mfd.Left_x;
        float y = mfd.Right_x;
        boolean two_parts = false;
        if (mfd.two_parts_domain) {
            float xx = x;
            if (x<0) xx = 360+x; if (y<0) y = 360+y;                
            Nlon1 = (int)(360-xx)*3600/DeltaLon;
            Nlon2 = (int) y*3600/DeltaLon+1;
            two_parts = true;
        }
        int shift = 0;
        if ((x < 0)&&(Left_x>=0))//only if previously it was East
            shift = (int)((360+x-Left_x)*3600/DeltaLat);
        else
            shift = (int)((mfd.Left_x-Left_x)*3600/DeltaLat);
        // due to OutOfMemory issue let's introduce scaling factor
        // which will reduce the relosution of data matrix and painting image 
        scale_factor = 1f;
        if (mfd.NewResolution > DeltaLat/60)
            scale_factor = (float)(1.0/((int)(mfd.NewResolution/(DeltaLat/60))));
        ReadFileData(f,nbytetoskip,shift,scale_factor,two_parts);
        Left_x  = mfd.Left_x;
        Upper_y = mfd.Upper_y;
        width = Math.round(Nlon*scale_factor);
        height= Math.round(Nlat*scale_factor);
        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        PaintImage(image, scale_factor);
        itopo_exist = false;
    }
    
    public void SaveMapData(FileWriter out) throws IOException
    {
        float[] b = getBounds();
        out.write(String.valueOf(b[0])); out.write("\t");
        out.write(String.valueOf(b[1])); out.write("\t");
        out.write(String.valueOf(b[2])); out.write("\t");
        out.write(String.valueOf(b[3])); out.write("\t");
        out.write(String.valueOf(Nlon)); out.write("\t");
        out.write(String.valueOf(Nlat)); out.write("\t");
        out.write(String.valueOf(threshold)); out.write("\t");
    }
    
       
/*    public void RestoreMap(){
         image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
         PaintImage(image, scale_factor);
    }
  */  
    public BufferedImage ReturnImage(boolean entire) {
    if (entire){ 
        BufferedImage returnimage
                    = new BufferedImage(image.getWidth(),image.getHeight(), image.getType());
        Graphics2D drawing = returnimage.createGraphics();
        drawing.drawImage(image, null, 0, 0);
        rect_selected = false;
        zoomedimage = image;
        left_x = Left_x;
        upper_y  = Upper_y;
        nlon = getNLON();
        nlat = getNLAT();
        return returnimage;
    }
    else {
        BufferedImage subimage = zoomedimage.getSubimage(rect.x,rect.y,rect.width,rect.height);
        Image im = subimage.getScaledInstance(width, height, Image.SCALE_FAST);
        BufferedImage returnimage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics2D g = returnimage.createGraphics();
        g.drawImage(im, 0, 0, null);
        rect_selected = true;
        zoomedimage = returnimage;
        left_x  = getXinDeg(rect.x);
        upper_y = getYinDeg(rect.y);
        nlon = Math.round((rect.width*nlon)/width);
        nlat = Math.round((rect.height*nlat)/height);
        return returnimage;
    }
    }

    public void StoreRectData(Rectangle r){
        rect = new Rectangle(r.x,r.y,r.width,r.height);
    }

    public void SetImage(BufferedImage ni) {
        BufferedImage newimage = new BufferedImage(ni.getWidth(),ni.getHeight(), ni.getType());
        Graphics2D drawing = newimage.createGraphics();
        drawing.drawImage(ni, null, 0, 0);
        image.flush();
        image = newimage;
    }
    
    public float getNLON(){ // in degrees
        return (float)((Nlon-1)*(double)(DeltaLon/3600.0));
    }
    
    public float getNLAT(){ // in degrees
        return (float)((Nlat-1)*(double)(DeltaLat/3600.0));
    }
    
    private float getXinDeg(float x){
        float xx = (float) (left_x + x*nlon/width);
        if (xx > 180.0) xx = (float) (-360 + xx);
        return xx; 
    }
    
    private float getYinDeg(float y){
        return (float)(upper_y - y*nlat/height);
    }

    public String getCoordstr(float x, float y){
        float xx,yy;
        xx = (float)(left_x + x*nlon/width);
        if (xx > 180){
            xx = (float)(-360 + xx);
        }
        yy = (float)(upper_y - y*nlat/height);
            String str = "(" + String.valueOf(xx)+","+String.valueOf(yy)+")";
            return str;
    }
    
    public Point2D.Float getCoord(float x, float y){
        Point2D.Float p = new Point2D.Float();
        double leftx = left_x;
        if (left_x<0) leftx = 360+left_x; 
        p.x = (float)(leftx + x*nlon/width);
        p.y = (float)(upper_y - y*nlat/height);
        return p;
    }
    
    public float[] getBounds(){
        float[] bounds = new float[4];
        bounds[0] = Left_x;
        bounds[1] = Left_x+nlon;
        if (bounds[1] > 180) bounds[1] = -360 + bounds[1];
        bounds[2] = Upper_y;
        bounds[3] = Upper_y-nlat;
        return bounds;
    }

    public boolean getFileReadStatus(){
        return FileNotFound;
    }
    
    private void ReadFileHeader(File ifile){
       int LatMinute = 0;
       int LonMinute = 0;
       FileNotFound = false;
       ByteBuffer dim_buffer = null;
       dim_buffer = ByteBuffer.allocate(128);
       try{
            FileInputStream fileInput = new FileInputStream(ifile);
            FileChannel fc = fileInput.getChannel();
            fc.read(dim_buffer);
            dim_buffer.order(ByteOrder.LITTLE_ENDIAN);
            dim_buffer.rewind();
            
            //=== HEADER =====================
            int Version   = dim_buffer.getInt();  //1,000,000,001
                Length    = dim_buffer.getInt();  //length of header
                DataType  = dim_buffer.getInt();  //1-depth,2-data density,3-grid radius 
                Upper_y   = dim_buffer.getInt();  //uppermost coordinate in degrees
                LatMinute = dim_buffer.getInt();  //minutes portion in uppermost coordinate 
                DeltaLat  = dim_buffer.getInt(24);//lattitudinal grid step in secongs
                Nlat      = dim_buffer.getInt(28);//number of rows
                Left_x    = dim_buffer.getInt(32);//leftmost coordinate in degrees
                LonMinute = dim_buffer.getInt(36);//minutes portion in leftmost coordinate
                DeltaLon  = dim_buffer.getInt(44);//longitudinal grid step in seconds
	        Nlon      = dim_buffer.getInt(48);//number of collumns
                MINval    = dim_buffer.getInt(52);//minimum value in data
                MAXval    = dim_buffer.getInt(56);//maximum value in data
                Precision = dim_buffer.getInt(64);//meters or 10th of meters
                Nbytes    = dim_buffer.getInt(72);//value represents size in bytes,  
                                                  //positive = integer, negative = float
       } catch (IOException e) {
            //System.out.println("Dym File Reading Error:" + e);    
            //System.exit(0);
            JOptionPane.showMessageDialog(null,"Check the path for map data in GMB file","File not found",JOptionPane.ERROR_MESSAGE);
            FileNotFound = true;
            return;
           }
       Left_x  = (float)(Left_x + LonMinute/60.0);
       Upper_y = (float)(Upper_y + LatMinute/60.0);
     }

    private void ReadFileData(File ifile, long nbytetoskip, int shift, float scale, boolean two_parts){

       ByteBuffer dim_buffer = null;
       dim_buffer = ByteBuffer.allocate(Nlon_pr*Nbytes);
       size_x = (int)(Nlon*scale);
       size_y = (int)(Nlat*scale);
       data = new int[size_x][size_y];
       if (two_parts){
       try{
            FileInputStream fileInput = new FileInputStream(ifile);
            FileChannel fc = fileInput.getChannel();
            for (int j=0;j<(int)(Nlat*scale);j++){
                fc.read(dim_buffer,nbytetoskip+(int)(Nbytes*Nlon_pr*j/scale));
                dim_buffer.order(ByteOrder.LITTLE_ENDIAN);                
                for (int i=0;i<(int)(Nlon1*scale);i++){
                    data[i][j] = dim_buffer.getInt(Nbytes*(shift+(int)(i/scale)));
                }
                dim_buffer.clear();
                dim_buffer.rewind();
            }
        } catch (IOException e) {
            Utils.FileReadError(ifile.getName());
          } 
       shift = 0;
       if (Nlon2 == 0) return;
       try{
            FileInputStream fileInput = new FileInputStream(ifile);
            FileChannel fc = fileInput.getChannel();
            for (int j=0;j<(int)(Nlat*scale);j++){
                fc.read(dim_buffer,nbytetoskip+(int)(Nbytes*Nlon_pr*j/scale));
                dim_buffer.order(ByteOrder.LITTLE_ENDIAN);                
                for (int i=0;i<(int)(Nlon2*scale);i++){
                    int ii = i+(int)(Nlon1*scale);
                    data[ii][j] = dim_buffer.getInt(Nbytes*(shift+(int)(i/scale)));
                }
                dim_buffer.clear();
                dim_buffer.rewind();
            }
        } catch (IOException e) {
            Utils.FileReadError(ifile.getName());
          }        
       }
       else{
       try{
            FileInputStream fileInput = new FileInputStream(ifile);
            FileChannel fc = fileInput.getChannel();
            for (int j=0;j<(int)(Nlat*scale);j++){
                fc.read(dim_buffer,nbytetoskip+(int)(Nbytes*Nlon_pr*j/scale));
                dim_buffer.order(ByteOrder.LITTLE_ENDIAN);                
                for (int i=0;i<(int)(Nlon*scale);i++){
                    data[i][j] = dim_buffer.getInt(Nbytes*(shift+(int)(i/scale)));
                }
                dim_buffer.clear();
                dim_buffer.rewind();
            }
        } catch (IOException e) {
            Utils.FileReadError(ifile.getName());
          }
       }
    }

    private void GetColors(){
        int min = 0; 
        int max = 255;
        land_col = new Color[land_ncol];
        ocean_col= new Color[ocean_ncol];
        for (int i=0; i<max+1; i++){
            ocean_col[i]   = new Color(min,min,i);
            ocean_col[i+max+1] = new Color(min,i,max);
            land_col[i]    = new Color(max-20,i,0);
        }
        for (int i=0; i<128; i++){
            land_col[i+max+1]  = new Color(max-20,max,i);
            land_col[i+max+1+128]  = new Color(max-i*2,max-20,128-i);
        }
    }
    
    private void PaintImage(BufferedImage bi, float scale){
        GetColors();
        Graphics2D g = image.createGraphics();
        g.drawImage(bi, 0, 0, null);
        int dx = Math.round(width/(Nlon*scale));
        int dy = Math.round(height/(Nlat*scale));
        double stepcol1 = Math.abs(MAXval/land_ncol);
        double stepcol2 = Math.abs(MINval/ocean_ncol);
        for (int i=0; i<(int)(Nlon*scale); i++){
            for (int j=0; j<(int)(Nlat*scale); j++){
                if (data[i][j]>0){
                    int k = (int)Math.round((MAXval-data[i][j])/stepcol1);
                    if (k > land_ncol-1) k = land_ncol-1;
                    g.setColor(land_col[k]);
                    g.fillRect(i*dx,j*dy,dx,dy);
                }else if (data[i][j]<0){
                    int k = (int)Math.round((data[i][j]-MINval)/stepcol2);
                    if (k > ocean_ncol-1) k = ocean_ncol-1;
                    g.setColor(ocean_col[k]);
                    g.fillRect(i*dx,j*dy,dx,dy);
                }
            }
        }
        g.dispose();
    }
    
     public int[][] GetDepth(){
        return data;
    }
    
    public int GetPixel(int x, int y) {
        if( ((x>=0)&&(y>=0)) && ((x<=width)&&(y<=height)) ){
            return image.getRGB(x,y);
        }
        return 0;
    }


 /*   public void Patch_Map(Point2D.Float coord[][], int nx, int ny) {
        Graphics2D drawing = image.createGraphics();
        int result = 0;
        Polygon p;
        Rectangle r;
        for(int i=0;i<nx-1;i++){
            for(int j=0;j<ny-1;j++){
                p = GetPolygon(coord,i,j);
                r = p.getBounds();      
                result = Get_Pattern(r);
                if(result == 0){    
                    drawing.setColor(land);
                    drawing.fillPolygon(p);              
                }else{
                    drawing.setColor(ocean);
                    drawing.fillPolygon(p);
                }                
            }
        }
        int cnt = 0;
        for(int i=1;i<nx-2;i++){
            for(int j=1;j<ny-2;j++){
                p = GetPolygon(coord,i,j);
                r = p.getBounds(); 
                result = Get_Pattern(r);
                if (result !=0){
                    int x  = Math.round((coord[i+1][j].x+coord[i][j].x)/2);
                    int y  = Math.round((coord[i][j+1].y+coord[i][j].y)/2);
                    int xl = Math.round((coord[i-1][j].x+coord[i][j].x)/2);
                    int xr = Math.round((coord[i+1][j].x+coord[i+2][j].x)/2);
                    int yu = Math.round((coord[i][j-1].y+coord[i][j].y)/2);
                    int yb = Math.round((coord[i][j+1].y+coord[i][j+2].y)/2);
                    int count = CheckNeighbors(x,y,xl,xr,yu,yb);
                    if (count >2){
                       drawing.setColor(land);
                       drawing.fillPolygon(p);
                       cnt++;
                    }
                }
            }
        }
        drawing.dispose();
    }*/
    
     public void Show_Patched_Mask(Graphics2D drawing, int[][] mask, Point[][] coord, int nx, int ny, int mask_flag, Color[] mask_colors) {
        Polygon p;
        for(int i=0;i<nx;i++){
            for(int j=0;j<ny;j++){
                p = GetPolygon(coord,i,j);
                int flag = mask[i][j];
                if (flag<0) {
                    int l = mask_colors.length;
                    drawing.setColor(mask_colors[l-1]);
                }
                else
                    drawing.setColor(mask_colors[flag]);
                drawing.fillPolygon(p);              
            }
        }
    }
    
    public void Show_Unpatched_Mask(Graphics2D drawing, int[][] mask, Point[][] coord, int nx, int ny, int mask_flag, Color[] mask_colors) {
        int cell_size = (int)Math.min(width/nx, height/ny);
        int d = Math.round(cell_size/2.5f);
        if (d<4) d = 4;
        Polygon p;
        for(int i=0;i<nx;i++){
            for(int j=0;j<ny;j++){
                int flag = mask[i][j];
                drawing.setColor(mask_colors[flag]);
                drawing.fillOval(Math.round(coord[i][j].x-d/2), Math.round(coord[i][j].y-d/2),d,d);
            }
        }
    }
    
    public void Show_Topo_Indices(Graphics2D drawing, int[][] mask, Point[][] coord, int nx, int ny) {
        Polygon p;
        Color[] palette = Utils.GetColors();
        int L = palette.length-1;
        for(int i=0;i<nx;i++){
            for(int j=0;j<ny;j++){
                int flag = mask[i][j];
                p = GetPolygon(coord,i,j);
                if (flag==0){
                    Color col = new Color(220,220,220);
                    drawing.setColor(col);
                } else {
                    int k = (int)(L*(1-itopo[i][j]));
                    drawing.setColor(palette[k]);
                }
                drawing.fillPolygon(p);              
            }
        }        
    }
    
    /*public void Patch_Mask_Rect(int[][] mask, Point2D.Float coord[][], Point[] ij, int mask_flag, Color[] mask_colors) {
        Graphics2D drawing = image.createGraphics();   
        int result = 0;
        Polygon p;
        Rectangle r;
        for (int i=ij[0].x; i<ij[1].x; i++){
            for (int j=ij[0].y; j<ij[1].y; j++){
                p = GetPolygon(coord,i,j);
                r = p.getBounds();      
                if(mask[i][j] == 0){    
                    drawing.setColor(mask_colors[0]);
                    drawing.fillPolygon(p);              
                }else{
                    for (int k=1; k<=mask_flag; k++){
                        if (mask[i][j]==k)
                            drawing.setColor(mask_colors[k]);
                    }
                    drawing.fillPolygon(p);
                }
            }
        }
        drawing.dispose();
    }*/
    private Polygon GetPolygon(Point coord[][], int i, int j){
        Polygon p = new Polygon();
        p.addPoint(coord[i][j].x,coord[i][j].y);
        p.addPoint(coord[i][j+1].x, coord[i][j+1].y);
        p.addPoint(coord[i+1][j+1].x, coord[i+1][j+1].y);
        p.addPoint(coord[i+1][j].x, coord[i+1][j].y);
        return p;
    }
    
    private Polygon GetPolygon(Point2D.Float coord[][], int i, int j){
        Polygon p = new Polygon();
        p.addPoint(Math.round(coord[i][j].x), Math.round(coord[i][j].y));
        p.addPoint(Math.round(coord[i][j+1].x), Math.round(coord[i][j+1].y));
        p.addPoint(Math.round(coord[i+1][j+1].x), Math.round(coord[i+1][j+1].y));
        p.addPoint(Math.round(coord[i+1][j].x), Math.round(coord[i+1][j].y));
        return p;
    }
    
 /*   public void FillRect(Rectangle r){
        Graphics2D drawing = image.createGraphics();
        drawing.setColor(land);
        drawing.fillRect(r.x,r.y,r.width,r.height);
        drawing.dispose();
    }

*/  public int Get_Pattern(Rectangle r){
        int xs = r.x;
        int ys = r.y;
        int xf = r.x+r.width;
        int yf = r.y+r.height;
        //start counting cells with depth under the threshold and above
 /*       float average = 0;
        for(int i=ys;i<yf;i++){
            for(int j=xs;j<xf;j++){
                average += data[j][i];
            }
        }
        average = average/((yf-ys)*(xf-xs));
        if (average > threshold){
            return 0;
        }else{
            return 1;
        }
  **/
        float sum1 = 0;
        float sum2 = 0;
        for (int i = ys; i < yf; i++) {
            for (int j = xs; j < xf; j++) {
                // average += data[j][i];
                if (data[j][i] <= threshold)
                    sum1++;
                else if (data[j][i] > threshold)
                    sum2++;         
            }
        }
        if (sum2 > sum1) {
            return 0;
        }
        else {
            return 1;
        }
  }

private float Sigmoid(float slope, double arg){
    float func;
    func = (float)(1.0/(1.0+Math.exp(-slope*arg)));
    return func;    
}

public float Get_TopoIndex(Rectangle r, int avdepth, float slope, int ix, int jx, int nx, int ny){
    if (!itopo_exist){
        itopo = new float[nx][ny];
        itopo_exist = true;
    } else {
        int Nx = itopo.length;
        int Ny = itopo[1].length;
        if ((Nx != nx)|| (Ny != ny)){
            itopo = null;
            itopo = new float[nx][ny];
        }
    }
        int xs = r.x;
        int ys = r.y;
        int xf = r.x+r.width;
        int yf = r.y+r.height;
        //split all points into two sets: below average depth and above;
        //compute weighted topographic index indicating probability for
        //tuna being in the current cell
        float average = 0;
        int m = 0; int n = 0;
        float dm = 0f;
        float dn = 0f;
        float sigma1 = 0f;
        float sigma2 = 0f;
        for(int i=ys;i<yf;i++){
            for(int j=xs;j<xf;j++){
                int depth = -data[j][i];
                average += Sigmoid(slope,depth-avdepth);
                if (depth>avdepth){
                    m++;
                    dm += depth;
                    sigma1 += Math.pow(depth-avdepth,2);
                } else {
                    n++;
                    dn += depth;
                    //sigma2 += Math.pow(depth-0.5*avdepth,2);
                }
            }
        }
        if (m>0) dm /= m; 
        if (n>0) dn /= n;
        for(int i=ys;i<yf;i++){
            for(int j=xs;j<xf;j++){
                int depth = -data[j][i]; 
                if (depth<=avdepth){
                    sigma2 += Math.pow(depth-dn,2);
                }
            }
        }
        if (m>1) sigma1 = (float)Math.sqrt(sigma1/(m-1));
        if (n>1) sigma2 = (float)Math.sqrt(sigma2/(n-1));
        //if (sigma1>10*sigma2 && dn>0) 
        //  return 1f;
        //float I = average/(m+n);
        //itopo[ix][jx] = I;
        float rm = (float)m/((float)(m+n));
        float rif = (float)Math.pow(rm,12);
        //float I = Sigmoid(slope,dm-avdepth)*rm+Sigmoid(slope,dn-avdepth)*(1-rm);
        float I = Sigmoid(slope,dm-avdepth)*rif+Sigmoid(slope,dn-avdepth)*(1-rif);
        itopo[ix][jx] = I;
        return I;
    }

    public boolean CheckDepth(int i, int j){
        if (i > size_x-1) i = size_x-1;
        if (j > size_y-1) j = size_y-1;
        if(data[i][j] <= threshold){
            return true;
        }else
            return false;
    }
    
    public boolean CheckDepth(Polygon p) {
        Rectangle r = p.getBounds(); 
        int res = Get_Pattern(r);
        if (res !=0)
            return true;
        else 
            return false;
    }
    
 /*   public boolean CheckColor(int x, int y){
        int rgba = image.getRGB(x,y);
        int R = (rgba >> 16) & 0xff;
        int G = (rgba >> 8) & 0xff;
        int B = rgba & 0xff;
        int r = 0; int g = 250; int b = 10;
        //int r = 0; int g = 0; int b = 0;
        if((R==r)&&(G==g)&&(B==b)){
            return true;
        }else{
            return false;
        }
    }
    
    public int CheckNeighbors(int i, int j, int il, int ir, int ju, int jb){
        int count=0;
        if (ir > size_x-1) ir = size_x-1;
        if (jb > size_y-1) jb = size_y-1;
        if (data[ir][j]>=threshold)
            count++;
        if (data[i][jb]>=threshold)
            count++;
        if (data[il][j]>=threshold)
            count++;
        if (data[i][ju]>=threshold)
            count++;
        return count;
    }
  */
    public void SaveMap(){
        float quality = 1.0f;
        String filename = ".//output//pmap.jpg";
        try {         
            ByteArrayOutputStream boutstream = new ByteArrayOutputStream();
            JPEGImageEncoder enc = JPEGCodec.createJPEGEncoder(boutstream);         
            JPEGEncodeParam enparam = JPEGCodec.getDefaultJPEGEncodeParam(image);         
            enparam.setQuality(quality, true);         
            enc.encode(image, enparam);         
            FileOutputStream fimage = new FileOutputStream(new File(filename));         
            boutstream.writeTo(fimage);         
            fimage.close();
        }catch (Exception e) { System.out.println(e); }
    }
}